using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SyncSocketModuleCore.SyncSocketModule
{
	public class SyncSocketClient
	{
		private Socket m_Socket;

		private int m_Id = -1;

		private string m_SocketName = "";

		private int m_ReceiveTimeOutMilliTime = 5000;

		private int m_SendTimeOutMilliTime = 5000;

		private int m_KeepAliveMilliTime = 5000;

		public string SocketName
		{
			get
			{
				return this.m_SocketName;
			}
			set
			{
				this.m_SocketName = value;
			}
		}

		private SyncSocketClient()
		{
		}

		public SyncSocketClient(int _Id, string _Name)
		{
			this.m_Id = _Id;
			this.m_SocketName = _Name;
		}

		public bool Close()
		{
			bool flag;
			if (this.m_Socket == null)
			{
				return true;
			}
			try
			{
				if (this.m_Socket.Connected)
				{
					this.ReceiveBufferClear("");
					this.m_Socket.Shutdown(SocketShutdown.Both);
					this.m_Socket.Close();
				}
				return true;
			}
			catch (Exception exception1)
			{
				Exception exception = exception1;
				this.LogProc(exception.Message);
				
				flag = false;
			}
			return flag;
		}

		public bool Connect(string _HostAddress, int _Port)
		{
			bool flag;
			IPEndPoint pEndPoint = null;
			try
			{
				pEndPoint = new IPEndPoint(IPAddress.Parse(_HostAddress), _Port);
			}
			catch (Exception exception1)
			{
				Exception exception = exception1;
				this.LogProc(exception.Message);
				
				flag = false;
				return flag;
			}
			if (this.m_Socket != null)
			{
				this.Close();
				this.m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
				{
					ReceiveTimeout = this.m_ReceiveTimeOutMilliTime,
					SendTimeout = this.m_SendTimeOutMilliTime
				};
			}
			else
			{
				this.m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
				{
					ReceiveTimeout = this.m_ReceiveTimeOutMilliTime,
					SendTimeout = this.m_SendTimeOutMilliTime
				};
			}
			try
			{
				this.m_Socket.Connect(pEndPoint);
				this.SetKeepAlive(this.m_Socket, this.m_KeepAliveMilliTime, 1000);
				return true;
			}
			catch (Exception exception3)
			{
				 Exception exception2 = exception3;
				this.LogProc(exception2.Message);
				
				flag = false;
			}
			return flag;
		}

        public bool IsConnected()
        {
            try
            {
                if (m_Socket == null)
                {
                    return false;
                }
                bool connected = m_Socket.Available != 0 || !m_Socket.Poll(1, SelectMode.SelectRead);
                if (!connected)
                {
                    connected = false;
                }
                return connected;
            }
            catch (Exception)
            {
                return false;
            }
        }


        private void LogProc(string _LogMsg)
		{
			if (this.OnErrorLogHandler == null)
			{
				return;
			}
			SyncSocketClientErrorArgs syncSocketClientErrorArg = new SyncSocketClientErrorArgs()
			{
				Message = _LogMsg
			};
			this.OnErrorLogHandler(this, syncSocketClientErrorArg);
		}

		public int Receive(byte[] _ReceivceBuffer, int _ReceiveByteSize, out SocketError _Error, string _ErrorIdentifyInfo = "")
		{
			_Error = SocketError.Success;
			int num = 0;
			try
			{
				num = this.m_Socket.Receive(_ReceivceBuffer, 0, _ReceiveByteSize, SocketFlags.None, out _Error);
				if ((int)_Error != 0)
				{
					this.LogProc(string.Concat(_ErrorIdentifyInfo, " SocketError : ", _Error.ToString()));
				}
			}
			catch (Exception exception1)
			{
				Exception exception = exception1;
				if (!string.IsNullOrWhiteSpace(_ErrorIdentifyInfo))
				{
					this.LogProc(_ErrorIdentifyInfo);
				}
				this.LogProc(exception.Message);
				
			}
			return num;
		}

		public int ReceiveBufferClear(string _ErrorIdentifyInfo = "")
		{
			int num = 0;
			try
			{
				if (this.m_Socket != null && this.m_Socket.Available > 0)
				{
					byte[] numArray = new byte[this.m_Socket.Available];
					num = this.m_Socket.Receive(numArray);
				}
			}
			catch (Exception exception1)
			{
				Exception exception = exception1;
				if (!string.IsNullOrWhiteSpace(_ErrorIdentifyInfo))
				{
					this.LogProc(_ErrorIdentifyInfo);
				}
				this.LogProc(exception.Message);
			
			}
			return num;
		}

		public int Send(ref byte[] _SendByteBuffer, int _SendByteSize, out SocketError _Error, string _ErrorIdentifyInfo = "")
		{
			_Error = SocketError.Success;
			int num = 0;
			try
			{
				num = this.m_Socket.Send(_SendByteBuffer, 0, _SendByteSize, SocketFlags.None, out _Error);
				if ((int)_Error != 0)
				{
					this.LogProc(string.Concat(_ErrorIdentifyInfo, " SocketError : ", _Error.ToString()));
				}
			}
			catch (Exception exception1)
			{
				Exception exception = exception1;
				if (!string.IsNullOrWhiteSpace(_ErrorIdentifyInfo))
				{
					this.LogProc(_ErrorIdentifyInfo);
				}
				this.LogProc(exception.Message);
				
			}
			return num;
		}

		private bool SetKeepAlive(Socket socket, int time, int interval)
		{
			bool flag;
			try
			{
				MemoryStream memoryStream = new MemoryStream(12);
				memoryStream.Write(BitConverter.GetBytes(1), 0, 4);
				memoryStream.Write(BitConverter.GetBytes(time), 0, 4);
				memoryStream.Write(BitConverter.GetBytes(interval), 0, 4);
				byte[] bytes = BitConverter.GetBytes(0);
				socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
				socket.IOControl((IOControlCode)(-1744830460), memoryStream.GetBuffer(), bytes);
				memoryStream.Close();
				return true;
			}
			catch (SocketException socketException1)
			{
				SocketException socketException = socketException1;
				this.LogProc(socketException.Message);
				this.LogProc(socketException.StackTrace);
				this.LogProc(socketException.Source);
				flag = false;
			}
			return flag;
		}

		public void SetReceiveTimeout(int _ReceiveTimeOutMilliTime)
		{
			this.m_ReceiveTimeOutMilliTime = _ReceiveTimeOutMilliTime;
			if (this.m_Socket != null)
			{
				this.m_Socket.ReceiveTimeout = this.m_ReceiveTimeOutMilliTime;
			}
			this.m_KeepAliveMilliTime = _ReceiveTimeOutMilliTime;
			if (this.m_Socket != null)
			{
				this.SetKeepAlive(this.m_Socket, this.m_KeepAliveMilliTime, 1000);
			}
		}

		public void SetSendTimeout(int _SendTimeOutMilliTime)
		{
			this.m_SendTimeOutMilliTime = _SendTimeOutMilliTime;
			if (this.m_Socket != null)
			{
				this.m_Socket.SendTimeout = this.m_SendTimeOutMilliTime;
			}
		}

		public event EventHandler<SyncSocketClientErrorArgs> OnErrorLogHandler;
	}
}